/**
 * 
 */
package org.jradweb.tools.generator.xml;

import java.io.File;
import java.io.IOException;
import java.util.Properties;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.apache.maven.plugin.logging.Log;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

/**
 * This Class is BeanOperator
 * 
 * @since Oct 12, 2007
 * @author Paul Wang
 */
public class XmlOperator {

	public static final int XML_TYPE_SPRING = 1;

	public static final int XML_TYPE_HIBERNATE = 2;

	public static final int XML_TYPE_XWORK = 3;

	private Log log;

	private File xmlFile;

	private File rootPath;

	protected Document document;

	protected String groupId;

	protected String modelName;

	protected String artifactId;

	public File getXmlFile() {
		return xmlFile;
	}

	public void setXmlFile(File xmlFile) {
		this.xmlFile = xmlFile;
	}

	public Log getLog() {
		return log;
	}

	public XmlOperator(File rootPath, String groupId, String artifactId,
			Log log) {
		this.groupId = groupId;
		this.modelName = modelName;
		this.artifactId = artifactId;
		this.rootPath = rootPath;
		this.log = log;
	}

	/**
	 * @deprecated
	 * @param springConfigFile
	 * @param log
	 * @param artifactId
	 * @throws IOException
	 * @throws ParserConfigurationException
	 * @throws SAXException
	 */
	public XmlOperator(File springConfigFile, Log log, String artifactId)
			throws IOException, ParserConfigurationException, SAXException {
		this.xmlFile = springConfigFile;
		this.log = log;
		this.artifactId = artifactId;
		this.document = this.initDocument(springConfigFile);
	}

	public void setLog(Log log) {
		this.log = log;
	}

	protected Node getBeanById(String id) {
		Element beans = document.getDocumentElement();
		log.debug("dao' " + beans.getNodeName() + ": ");
		NodeList beansList = beans.getChildNodes();
		for (int i = 0; i < beansList.getLength(); i++) {
			Node bean = beansList.item(i);
			if (bean.getNodeName().equals("bean")) {
				log.debug("bean:");
				NamedNodeMap nnm = bean.getAttributes();
				for (int j = 0; nnm != null && j < nnm.getLength(); j++) {
					Node node = nnm.item(j);
					if (node.getNodeName().equals("id")
							&& node.getNodeValue().equals(id))
						return node;
				}
			}
		}
		return null;
	}

	protected Node getNodeByName(String name) {
		Element root = document.getDocumentElement();
		if (root.getNodeName().equals(name))
			return root;
		return this.findNode(name, root);
	}

	private Node findNode(String name, Node pNode) {
		NodeList nodeList = pNode.getChildNodes();
		for (int i = 0; i < nodeList.getLength(); i++) {
			Node node = nodeList.item(i);
			// this.getLog().info("node name:"+node.getNodeName());
			if (node.getNodeName().equals(name)) {
				return node;
			} else {
				Node findedNode = findNode(name, node);
				if (findedNode != null)
					return findedNode;
			}
		}
		return null;
	}

	protected Document initDocument(File file) throws IOException,
			ParserConfigurationException, SAXException {

		DocumentBuilder builder = javax.xml.parsers.DocumentBuilderFactory
				.newInstance().newDocumentBuilder();
		document = builder.parse(file);

		Element beans = document.getDocumentElement();
		log.debug("dao' " + beans.getNodeName() + ": ");
		NodeList beansList = beans.getChildNodes();
		// for (int i = 0; i < beansList.getLength(); i++) {
		// Node bean = beansList.item(i);
		// if (bean.getNodeName().equals("bean")) {
		// log.debug("bean:");
		// NamedNodeMap nnm = bean.getAttributes();
		// for (int j = 0; nnm != null && j < nnm.getLength(); j++) {
		// Node node = nnm.item(j);
		// this.getLog().debug(
		// node.getNodeName() + " = " + node.getNodeValue());
		// }
		// }
		// }

		DocumentType docType = document.getDoctype();
		log.debug("doc type: " + docType);
		return document;
	}

	protected void saveDocument(int xmlType) throws TransformerException {
		Transformer transformer;
		try {
			transformer = TransformerFactory.newInstance().newTransformer();
			Properties properties = transformer.getOutputProperties();
			properties.setProperty(OutputKeys.ENCODING, "UTF-8");
			properties.setProperty(OutputKeys.METHOD, "xml");
			properties.setProperty(OutputKeys.INDENT, "yes");

			if (xmlType == XML_TYPE_SPRING) {
				properties.setProperty(OutputKeys.DOCTYPE_SYSTEM,
						"http://www.springframework.org/dtd/spring-beans.dtd");
				properties.setProperty(OutputKeys.DOCTYPE_PUBLIC,
						"-//SPRING//DTD BEAN//EN");
			} else if (xmlType == XML_TYPE_HIBERNATE) {
				properties
						.setProperty(OutputKeys.DOCTYPE_SYSTEM,
								"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd");
				properties.setProperty(OutputKeys.DOCTYPE_PUBLIC,
						"-//Hibernate/Hibernate Configuration DTD 3.0//EN");
			} else if (xmlType == XML_TYPE_XWORK) {
				properties.setProperty(OutputKeys.DOCTYPE_SYSTEM,
						"http://www.opensymphony.com/xwork/xwork-1.0.dtd");
				properties.setProperty(OutputKeys.DOCTYPE_PUBLIC,
						"-//OpenSymphony Group//XWork 1.0//EN");
			}
			transformer.setOutputProperties(properties);

			transformer.transform(new DOMSource(document), new StreamResult(
					this.getXmlFile()));

		} catch (TransformerException e) {
			throw e;
		} catch (TransformerFactoryConfigurationError e) {
			throw e;
		} finally {

		}

	}

	public Document getDoc() {
		return document;
	}

}
